#include "httprequest.h"
const std::unordered_set<std::string> HttpRequest::DEFAULT_HTML
{
    "/index",
    "/hello",
    "/head"
};
void HttpRequest::init()
{
    method_ = path_ = version_ = body_ = "";
    ParseStatus_ =  ParseRequestLine;
    Head_.clear();
}
bool HttpRequest::Parse(Buffer_::Buffer& buff)
{
    if(buff.readableBytes() <=0)
    {
        return false;
    }

    while((buff.readableBytes()>0) && (ParseStatus_ != ParseFinsh))
    {
        /* std::search() 函数*/
        const char *lineEnd = std::search(buff.RIndex_cptr(),buff.WIndex_cptr(),&CRLF[0],&CRLF[0]+2);
        std::string line(buff.RIndex_cptr(),lineEnd);
        //这里加回 "\r\n"是因为 在ParseLinde()函数中有特殊的处理方式
        line +="\r\n";  
        switch(ParseStatus_)
        {
        case ParseRequestLine:
        {
            if( ParseLine(line) ==false)
            {
                return false;
            }
            Parsepath();
            break;
        }
        case ParseHead:
        {
            ParseHeader(lineEnd);
            if(buff.readableBytes() <=2 )//请求报文没有报文体
            {
                ParseStatus_ = ParseFinsh;
            }
            break;
        }
        case ParseBody:
        {
            Parsebody(/*line*/);
            break;
        }
        default:
            break;
        }
    }
    if(buff.readableBytes()==0 && ParseStatus_!= ParseFinsh) 
    {  
        ParseStatus_ = ParseErrno; 
        LOG_ERRNO("[%s] [%s] [%s]\n",method_.c_str(),path_.c_str(),version_.c_str());
        return 0; 
    }
    LOG_INFO("[%s] [%s] [%s]\n",method_.c_str(),path_.c_str(),version_.c_str());
    return true;
}
bool HttpRequest::Parsepath()
{//注意这里会有几个细节 
//客户会给出空路径 例如 192.168.136.128:5005 这样的请求
//客户会给出我们认为的正确路径 例如192.168.136.128:5005/index
//客户会自作主张给出全路径 例如 192.168.136.128:5005/index.html
    if(path_.length() == 0 || path_ == "/")
    {//服务器给出默认路径
        path_="/index.html";
        return true;
    }
    else if(path_.find(".",0) == std::string::npos )
    {//客户给出路径 index
        if(DEFAULT_HTML.find(path_) != DEFAULT_HTML.end())
        {
            path_ += ".html";
            return true;
        }
        else
        {   return false;   }
    }
    else if(path_.find(".",0)!=std::string::npos)
    {//客户给出路径 index.???
        auto poi_index = path_.find(".",0);
        std::string path_temp(&path_[0],&path_[poi_index]);
        if(DEFAULT_HTML.find(path_temp) != DEFAULT_HTML.end())
        {
            return true;
        }
        else
        {   return false;   }
    }
    return false;
}
bool HttpRequest::ParseLine(std::string& buff)
{
    int f_index = 0;
	int r_index = 0;
	f_index = buff.find(' ',r_index);
	method_.append(&buff[0],&buff[f_index]);
	r_index = f_index+1;
	f_index = 0;

	f_index = buff.find(' ', r_index);
	path_.append(&buff[r_index], &buff[f_index]);
	r_index = f_index+1;	
	f_index = 0;

	f_index = buff.find("\r",r_index);
	version_.append(&buff[r_index], &buff[f_index]);
	r_index = f_index + 1;
	f_index = 0;


    ParseStatus_ = ParseHead;
    //路径可能是空的 但 方法和version绝不可能为空
    if((method_.length()&&version_.length()) == 0)
    {
        LOG_ERRNO("RequestLine Error\n");
        return false;
    }
    return true;
}
bool HttpRequest::ParseHeader(std::string buff)
{
    //解决 属性名:属性值 的数据
    std::unordered_map<std::string, std::string> head;
	size_t ff_index = 0;
	size_t p_index = 0;
	size_t k_index = 0;
	size_t colon_index = 0;
    bool status = false;
	while(1)
	{
		std::pair<std::string, std::string> test;
		ff_index = buff.find(CRLF,ff_index,2);
		p_index = ff_index+2;
		colon_index = buff.find(':', ff_index);	//[p_index,colon_index] 为键
		k_index = colon_index + 1;
		ff_index = buff.find(CRLF, k_index,2);	//[k_index,ff_index] 为值

		if (ff_index == std::string::npos || colon_index == std::string::npos)
		{
            LOG_DEBUG("请求头信息不全 解析失败 code line: 147");
			break;
		}
		std::string str = "\r";
		test.first.append(&buff[p_index], &buff[colon_index]);
		test.second.append(&buff[k_index], &buff[ff_index]);
		head.insert(test);
        //这段算法在HTTP请求不分段的情况下是没有问题的
		if ((buff.length() - (ff_index + 2)) <= 2)//请求头解析完毕
		{
			int end = buff.length() - (ff_index + 2);
			if (end == 2)
			{
				if ((buff.at(ff_index + 2) == '\r') && (buff.at(ff_index + 3) == '\n')) //2
				{
                    status = true;
					break;
				}
			}
			else if (end == 1)
			{
				if (buff.at(ff_index + 2 == '\r') && end == 1)	//==1
				{
                    LOG_DEBUG("解析完成,请求头信息不全,解析失败 code line:170")
					break;
				}
			}
			else //==0
			{
                LOG_DEBUG(" 请求头信息不全 解析失败 code line:176")
				break;
			}
		}
        break;
	}
    ParseStatus_ = ParseBody;
    return status;

}
bool HttpRequest::Parsebody(/*std::string&buff*/ )
{
    ParseStatus_ = ParseFinsh;
    //LOG_INFO("暫時不设置请求体,只回应 GET 请求");
    return true;
}
bool HttpRequest::isKeepAlive() const
{
    if(Head_.count("Connection") == 1)
    {
        return (Head_.find("Connection")->second == "keep-alive") && (version_ =="HTTP/1.1");
    }
    return false;
}
std::string HttpRequest::getMethod()
{
    return method_;
}
std::string HttpRequest::getVersion()
{
    return version_;
}
std::string HttpRequest::path() const
{
    return path_;
}
std::string& HttpRequest::path()
{
    return path_;
}












